#ifndef MY_STRING_H
#define MY_STRING_H

#include <cstring>
#include <iostream>
#include <limits>
using std::cout;
using std::endl;

namespace sympsel {
class string

{
    friend std::ostream& operator<<(std::ostream& _cout, const string& s);

    friend std::istream& operator>>(std::istream& _cin, string& s);

   public:
    typedef char* iterator;
    typedef const char* const_iterator;

    string(const char* str = "") {
        int size = strlen(str);
        _str = new char[size + 1];
        strcpy(_str, str);
        _size = size;
        _capacity = size;
    }

    string(const char c) {
        _str = new char[2];
        _str[0] = c;
        _capacity = _size = 1;
    }

    string(const string& s) {
        _str = new char[s._size + 1];
        strcpy(_str, s._str);
        _size = s._size;
        _capacity = s._capacity;
    }

    string& operator=(const string& s);

    ~string() { delete[] _str; }

    //////////////////////////////////////////////////////////////

    // iterator

    iterator begin() { return _str; }

    iterator end() { return _str + _size; }

    iterator rbegin() { return _str + _size - 1; }

    iterator rend() { return _str - 1; }

    const_iterator begin() const { return _str; }

    const_iterator end() const { return _str + _size; }

    const_iterator rbegin() const { return _str + _size - 1; }

    const_iterator rend() const { return _str - 1; }

    /////////////////////////////////////////////////////////////

    // modify

    void push_back(char c);

    string& operator+=(char c);

    void append(const char* str);

    string& operator+=(const char* str);

    string& operator+=(const string& str);

    void clear();

    void swap(string& s);

    const char* c_str() const { return _str; }

    /////////////////////////////////////////////////////////////

    // capacity

    size_t size() const { return _size; }

    size_t capacity() const { return _capacity; }

    bool empty() const { return _size == 0; }

    void resize(size_t n, char c = '\0');

    void reserve(size_t n);

    /////////////////////////////////////////////////////////////

    // access

    char& operator[](size_t index) { return _str[index]; }

    const char& operator[](size_t index) const { return _str[index]; }

    /////////////////////////////////////////////////////////////

    // relational operators

    bool operator<(const string& s);

    bool operator<=(const string& s);

    bool operator>(const string& s);

    bool operator>=(const string& s);

    bool operator==(const string& s);

    bool operator!=(const string& s);

    // 返回c在string中第一次出现的位置

    size_t find(char c, size_t pos = 0) const;

    size_t find(char c, size_t pos, size_t n) const;

    // 返回子串s在string中第一次出现的位置

    int str_cmp(const string& s) const;

    int str_cmp(const string& s, size_t begin, size_t n) const;

    size_t find(const char* s, size_t pos = 0) const;

    // 在pos位置上插入字符c/字符串str，并返回该字符的位置

    string& insert(size_t pos, char c);

    string& insert(size_t pos, const char* str);

    string& insert(size_t pos, const string& s);

    // 删除pos位置上的元素，并返回该元素的下一个位置

    string& erase(size_t pos = 0, size_t len = npos);

    string substr(size_t pos = 0, size_t len = npos);

    static const size_t npos = std::numeric_limits<size_t>::max();

    inline static void swap(string& s1, string& s2) {
        s1.swap(s2);
    }

   private:
    char* _str;

    size_t _capacity;

    size_t _size;
};
}  // namespace sympsel

#endif  // MY_STRING_H
